#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/10/10 6:34 下午
# file: main.py
"""
import datetime
from typing import Callable

import uvicorn
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.exception_handlers import (
    http_exception_handler,
    request_validation_exception_handler,
)
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from starlette.exceptions import HTTPException as StarletteHTTPException

from app.api.api_v1.api import api_router
from app.config.setting import settings
from app.utils.logger_utils import log

app = FastAPI(
    title=settings.project_name, openapi_url=f"{settings.api_v1_sre}/openapi.json"
)


async def custom_http_exception_handler(
        request: Request, exc: HTTPException
) -> Response:
    log.error(f"抛出一个 HTTP Exception: {repr(exc)}")
    return await http_exception_handler(request, exc)


async def validation_exception_handler(
        request: Request, exc: RequestValidationError
) -> Response:
    log.error(f"抛出一个 Validation Exception: {repr(exc)}")
    return await request_validation_exception_handler(request, exc)


app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(api_router, prefix=settings.api_v1_sre)
app.add_exception_handler(StarletteHTTPException, custom_http_exception_handler)
app.add_exception_handler(RequestValidationError, validation_exception_handler)


@app.middleware("http")
async def logging_request(request: Request, call_next: Callable) -> Response:
    start_ms = datetime.datetime.now()
    response = await call_next(request)
    end_ms = datetime.datetime.now()
    request_time = (end_ms - start_ms).total_seconds()
    request_time_str = (
        f"{round(request_time, 2)}s"
        if request_time > 1
        else f"{round(request_time * 1000, 2)}ms"
    )
    log.info(
        f"请求路径：{request.url.path} - 请求耗时：{request_time_str} - 响应状态码：{response.status_code}"
    )
    return response


if __name__ == "__main__":
    uvicorn.run("main:app", debug=True, env_file="config/dev.env")
